package com.leo.common.core.exception;

import com.leo.common.core.enums.ExceptionCodeEnum;
import com.leo.common.core.model.Result;
import com.leo.common.core.util.MessageUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @Description:
 * @Author: johnny
 * @Date: 2020/4/9 16:25
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

	@Resource
	MessageUtils messageUtils;

	@ExceptionHandler(value = MethodArgumentNotValidException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result methodArgumentNotValid(HttpServletRequest req, MethodArgumentNotValidException ex) {

		Result result = new Result();
		result.setCode(ExceptionCodeEnum.BIZ_BAD_REQUEST.getCode());
		List<ObjectError> errors = ex.getBindingResult().getAllErrors();
		StringBuffer errorMsg = new StringBuffer();

		errors.forEach(x -> errorMsg.append(messageUtils.get(x.getDefaultMessage())).append(";"));
		log.error("参数绑定异常,ex = {}", errorMsg.toString());
		result.setMsg(errorMsg.toString());
		return result;
	}

	@ExceptionHandler(value = BindException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result methodArgumentBindException(HttpServletRequest req, BindException ex) {
		Result result = new Result();
		result.setCode(ExceptionCodeEnum.BIZ_BAD_REQUEST.getCode());
		List<ObjectError> errors = ex.getBindingResult().getAllErrors();
		StringBuffer errorMsg = new StringBuffer();
		errors.forEach(x -> errorMsg.append(messageUtils.get(x.getDefaultMessage())).append(";"));
		log.error("参数类型异常,ex = {}", errorMsg.toString());
		result.setMsg(errorMsg.toString());
		return result;
	}

	@ExceptionHandler(HttpMessageNotReadableException.class)
	@ResponseStatus(HttpStatus.FORBIDDEN)
	public Result httpMessageNotReadableException(HttpMessageNotReadableException e) {
		log.error("参数格式异常 ex={}", e.getMessage());
		Result result = new Result();
		result.setCode(ExceptionCodeEnum.BIZ_BAD_REQUEST.getCode());
		result.setMsg(messageUtils.get(ExceptionCodeEnum.BIZ_BAD_REQUEST.getMsg()) + ":" + e.getLocalizedMessage());
		return result;
	}

	/**
	 * AccessDeniedException
	 * @param e the e
	 * @return Result
	 */
	@ExceptionHandler(AccessDeniedException.class)
	@ResponseStatus(HttpStatus.FORBIDDEN)
	public Result handleAccessDeniedException(AccessDeniedException e) {
		log.error("拒绝授权异常信息 ex={}", e.getMessage());
		Result result = new Result();
		result.setCode(ExceptionCodeEnum.BIZ_FORBIDDEN.getCode());
		result.setMsg(messageUtils.get(ExceptionCodeEnum.BIZ_FORBIDDEN.getMsg()));
		return result;
	}

	/**
	 * 业务异常.
	 * @param e the e
	 * @return Result
	 */
	@ExceptionHandler(BizException.class)
	@ResponseStatus(HttpStatus.OK)
	public Result handleGlobalBizException(BizException e) {
		log.error("业务异常信息 ex={}", e.getLocalizedMessage());
		return Result.failed(e.getLocalizedMessage());
	}

	/**
	 * 业务code异常.
	 * @param e the e
	 * @return Result
	 */
	@ExceptionHandler(com.leo.common.core.exception.BizCodeException.class)
	@ResponseStatus(HttpStatus.OK)
	public Result handleGlobalBizException(com.leo.common.core.exception.BizCodeException e) {
		log.error("业务code异常信息 ex={}", e.getLocalizedMessage());
		if (e.getExceptionCodeEnum() != null) {
			Result result = new Result();
			result.setCode(e.getExceptionCodeEnum().getCode());
			result.setMsg(messageUtils.get(e.getExceptionCodeEnum().getMsg()));
			return result;
		}
		return Result.failed(e.getLocalizedMessage());
	}

	@ExceptionHandler(BadRequestException.class)
	@ResponseStatus(HttpStatus.OK)
	public Result badRequestException(BadRequestException e) {
		log.error("错误的请求异常信息 ex={}", e.getLocalizedMessage());
		Result result = new Result();
		result.setCode(e.getExceptionCode());
		result.setMsg(e.getMessage());

		return result;
	}

	/**
	 * 全局异常.
	 * @param e the e
	 * @return Result
	 */
	@ExceptionHandler(Exception.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result handleGlobalException(Exception e) {
		log.error("全局异常信息 ex={}", e.getMessage(), e);
		Result result = new Result();
		result.setCode(ExceptionCodeEnum.SERVER_ERROR.getCode());
		result.setMsg(messageUtils.get("internal.server.error"));
		// return Result.failed(e.getLocalizedMessage());
		return result;
	}

}
